package com.gopay.bis.service.bank.autoroute.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.autoroute.BankRouteBase;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.bis.RouteMessage;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.dao.CommonQueryDAO;

/**
 * 获取银行自动路由实现
 * 
 * @BankRouteServiceImpl.java
 * @author zhengxue
 * @2016-10-8 下午2:59:17 www.gopay.com.cn Inc.All rights reserved.
 */
@Service(value = "bankRouteService")
public class BankRouteServiceImpl extends BankRouteBase {
    private final static Logger logger = LoggerFactory.getLogger(BankRouteServiceImpl.class);
    @Resource(name = "commonQueryDAO")
    private CommonQueryDAO commonQueryDAO;

    @Resource(name = "bisBankExtConfigManager")
    BisBankExtConfigManager bisBankExtConfigManager;

    @Override
    protected BaseBisBankExtConfig getBankRoute(RouteMessage routeMessage) {
        BaseBisBankExtConfig config = null;
        // 根据商户ID获取商户方案
        List<Object[]> solutionIds = getSolutionByCustId(routeMessage.getCustId());
        if (solutionIds == null || solutionIds.isEmpty()) {
            // 若无商户方案则获取通用方案
            return getNormalSolution(routeMessage);
        }

        // 根据方案获取商户规则
        List<Integer> specialRuleIds = getSpecialRuleIds(solutionIds, routeMessage);
        if (specialRuleIds == null || specialRuleIds.isEmpty()) {
            // 若无商户规则则获取通用方案
            return getNormalSolution(routeMessage);
        }

        List<String> channels = getSpecialChannelCodes(specialRuleIds, routeMessage);
        if (channels == null || channels.isEmpty()) {
            // 若无商户渠道则获取通用方案
            return getNormalSolution(routeMessage);
        }

        String channelCode = channels.get(0);
        routeMessage.setChanellCode(channelCode);
        config = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                BisBankBusinessProd.get(routeMessage.getProdCode()), BisBankInterfaceChannel.get(channelCode),
                routeMessage.getBankCode());
        return config;
    }

    /**
     * 根据商户id获取商户方案
     * 
     * @param custId
     * @return
     */
    protected List<Object[]> getSolutionByCustId(String custId) {
        StringBuilder sql = new StringBuilder();
        sql.append(" select solu.SOLUTION_ID, solu.SOLUTION_NAME from BIS_SPECIAL_ROUTE_SOLUTION solu ");
        sql.append(" left join BIS_SPECIAL_ROUTE_SOLU_CUST csolu on solu.SOLUTION_ID = csolu.SOLUTION_ID ");
        sql.append(" where csolu.CUST_ID = :custId ");
        sql.append(" and csolu.IS_DELETE = :isDelete ");
        sql.append(" and solu.IS_DELETE = :isDelete ");
        sql.append(" and solu.IS_ENABLE = :isEnable ");

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("custId", custId);
        params.put("isDelete", 1);
        params.put("isEnable", 1);
        List<Object[]> list = commonQueryDAO.findBySql(sql.toString(), params);
        return list;
    }

    /**
     * 根据商户方案获取商户规则
     * 
     * @param list
     * @param routeMessage
     * @return
     */
    protected List<Integer> getSpecialRuleIds(List<Object[]> list, RouteMessage routeMessage) {
        List<Integer> specialRuleIds = new ArrayList<Integer>();
        for (Object[] solutionId : list) {
            Integer sId = ((BigDecimal) solutionId[0]).intValue(); // 商户方案ID
            routeMessage.setSolutionId(sId); // 赋值方案ID
            routeMessage.setSolutionName((String) solutionId[1]); // 赋值方案名称
            logger.error("BankRouteServiceImpl getSpecialSolutionIds: " + sId);

            StringBuilder sql = new StringBuilder();
            sql.append(" select rule.RULE_ID, rule.rule_name from BIS_SPECIAL_ROUTE_RULE rule ");
            sql.append(" left join BIS_SPECIAL_ROUTE_SOLU_RULE srule on rule.RULE_ID = srule.RULE_ID ");
            sql.append(" where srule.SOLUTION_ID = :solutionId ");
            sql.append(" and srule.IS_DELETE = :isDelete ");
            sql.append(" and rule.IS_DELETE = :isDelete ");
            sql.append(" and rule.IS_ENABLE = :isEnable ");
            sql.append(" and rule.BANK_CODE = :bankCode ");
            sql.append(" and rule.PROD_CODE = :procCode ");

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("solutionId", sId);
            params.put("isDelete", 1);
            params.put("isEnable", 1);
            params.put("bankCode", routeMessage.getBankCode());
            params.put("procCode", routeMessage.getProdCode());
            // 根据商户方案ID、银行码、渠道码获取商户规则
            List<Object[]> ruleList = commonQueryDAO.findBySql(sql.toString(), params);

            if (ruleList == null || ruleList.isEmpty()) {
                // 商户用规则
                logger.error("BankRouteServiceImpl getSpecialRuleIds is null");
                continue;
            }

            for (Object[] routeRuleId : ruleList) {
                Integer rId = ((BigDecimal) routeRuleId[0]).intValue();
                routeMessage.setRuleId(rId); // 赋值商户规则ID
                routeMessage.setRuleName((String) routeRuleId[1]); // 赋值商户规则名称
                logger.error("BankRouteServiceImpl getSpecialRuleIds: " + rId);
                specialRuleIds.add(rId);
            }
        }
        return specialRuleIds;
    }

    /**
     * 根据商户规则获取商户渠道
     * 
     * @param list
     * @param routeMessage
     * @return
     */
    protected List<String> getSpecialChannelCodes(List<Integer> list, RouteMessage routeMessage) {
        List<String> channels = new ArrayList<String>();
        for (Integer ruleId : list) {
            StringBuilder sql = new StringBuilder();
            sql.append(" select b.CHANNEL_CODE, b.START_EXP, b.END_EXP from BIS_SPECIAL_ROUTE_CHANNEL_DTL b ");
            sql.append(" where b.IS_DELETE = :isDelete ");
            sql.append(" and b.RULE_ID = :ruleId ");
            sql.append(" and b.START_EXP <= :transAmt ");
            sql.append(" and b.END_EXP > :transAmt ");

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("isDelete", 1);
            params.put("ruleId", ruleId);
            params.put("transAmt", routeMessage.getTransAmt());
            // 根据商户规则ID、交易金额获取银行渠道码
            List<Object[]> channelList = commonQueryDAO.findBySql(sql.toString(), params);

            if (channelList == null || channelList.isEmpty()) {
                // 无商户规则
                logger.error("BankRouteServiceImpl getSpecialChannelCodes is null");
                continue;
            }

            for (Object[] channel : channelList) {
                routeMessage.setStartExp((BigDecimal) channel[1]); // 赋值金额区间
                routeMessage.setEndExp((BigDecimal) channel[2]); // 赋值金额区间
                logger.error("BankRouteServiceImpl getSpecialChannelCodes: " + channel[0]);
                channels.add((String) channel[0]);
            }
        }
        return channels;
    }

    /**
     * 获取通用方案
     * 
     * @return
     */
    protected BaseBisBankExtConfig getNormalSolution(RouteMessage routeMessage) {
        BaseBisBankExtConfig config = null;
        StringBuilder sql = new StringBuilder();
        sql.append(" select b.SOLUTION_ID, b.SOLUTION_NAME from BIS_NORMAL_ROUTE_SOLUTION b ");
        sql.append(" where b.IS_DELETE = :isDelete ");
        sql.append(" and b.IS_ENABLE = :isEnable ");

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("isDelete", 1);
        params.put("isEnable", 1);
        List<Object[]> list = commonQueryDAO.findBySql(sql.toString(), params);
        if (list == null || list.isEmpty()) {
            // 无通用方案
            logger.error("BankRouteServiceImpl getNormalSolution is null");
            return config;
        }

        List<Integer> ruleIds = getNormalRuleIds(list, routeMessage); // 获取通用规则
        if (ruleIds == null || ruleIds.isEmpty()) {
            // 无通用规则
            logger.error("BankRouteServiceImpl getNormalRule is null");
            return config;
        }

        List<String> channels = getNormalChannelCodes(ruleIds, routeMessage);
        if (channels == null || channels.isEmpty()) {
            // 未获取银行渠道
            logger.error("BankRouteServiceImpl getNormalChannel is null");
            return config;
        }

        String channelCode = channels.get(0);
        routeMessage.setChanellCode(channelCode);
        config = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(
                BisBankBusinessProd.get(routeMessage.getProdCode()), BisBankInterfaceChannel.get(channelCode),
                routeMessage.getBankCode());
        return config;
    }

    /**
     * 获取通用规则
     * 
     * @param list
     * @param routeMessage
     * @return
     */
    protected List<Integer> getNormalRuleIds(List<Object[]> list, RouteMessage routeMessage) {
        List<Integer> ruleIds = new ArrayList<Integer>();
        for (Object[] solutionId : list) {
            Integer sId = ((BigDecimal) solutionId[0]).intValue(); // 方案ID
            routeMessage.setSolutionId(sId); // 赋值方案ID
            routeMessage.setSolutionName((String) solutionId[1]); // 赋值方案名称
            logger.error("BankRouteServiceImpl getNormalSolutionIds: " + sId);

            StringBuilder sqlRule = new StringBuilder();
            sqlRule.append(" select rule.RULE_ID, rule.rule_name from BIS_NORMAL_ROUTE_RULE rule ");
            sqlRule.append(" left join BIS_NORMAL_ROUTE_SOLU_RULE srule on rule.RULE_ID = srule.RULE_ID ");
            sqlRule.append(" where srule.SOLUTION_ID = :solutionId ");
            sqlRule.append(" and srule.IS_DELETE = :isDelete ");
            sqlRule.append(" and rule.IS_DELETE = :isDelete ");
            sqlRule.append(" and rule.IS_ENABLE = :isEnable ");
            sqlRule.append(" and rule.BANK_CODE = :bankCode ");
            sqlRule.append(" and rule.PROD_CODE = :procCode ");

            Map<String, Object> ruleParams = new HashMap<String, Object>();
            ruleParams.put("solutionId", sId);
            ruleParams.put("isDelete", 1);
            ruleParams.put("isEnable", 1);
            ruleParams.put("bankCode", routeMessage.getBankCode());
            ruleParams.put("procCode", routeMessage.getProdCode());
            // 根据通用方案ID、银行码、产品码获取通用规则
            List<Object[]> ruleList = commonQueryDAO.findBySql(sqlRule.toString(), ruleParams);

            if (ruleList == null || ruleList.isEmpty()) {
                // 无通用规则
                logger.error("BankRouteServiceImpl getNormalRuleIds is null");
                continue;
            }

            for (Object[] routeRuleId : ruleList) {
                Integer rId = ((BigDecimal) routeRuleId[0]).intValue();
                routeMessage.setRuleId(rId); // 赋值规则ID
                routeMessage.setRuleName((String) routeRuleId[1]); // 赋值规则名称
                logger.error("BankRouteServiceImpl getNormalRuleIds: " + rId);
                ruleIds.add(rId);
            }
        }
        return ruleIds;
    }

    /**
     * 根据通用规则获取银行渠道
     * 
     * @param list
     * @param routeMessage
     * @return
     */
    protected List<String> getNormalChannelCodes(List<Integer> list, RouteMessage routeMessage) {
        List<String> channels = new ArrayList<String>();
        for (Integer ruleId : list) {
            StringBuilder sql = new StringBuilder();
            sql.append(" select b.CHANNEL_CODE, b.START_EXP, b.END_EXP from BIS_NORMAL_ROUTE_CHANNEL_DTL b ");
            sql.append(" where b.IS_DELETE = :isDelete ");
            sql.append(" and b.RULE_ID = :ruleId ");
            sql.append(" and b.START_EXP <= :transAmt ");
            sql.append(" and b.END_EXP > :transAmt ");

            Map<String, Object> params = new HashMap<String, Object>();
            params.put("isDelete", 1);
            params.put("ruleId", ruleId);
            params.put("transAmt", routeMessage.getTransAmt());
            // 根据通用规则ID、交易金额获取银行渠道码
            List<Object[]> channelList = commonQueryDAO.findBySql(sql.toString(), params);

            if (channelList == null || channelList.isEmpty()) {
                // 无通用渠道
                logger.error("BankRouteServiceImpl getNormalChannelCodes is null");
                continue;
            }

            for (Object[] channel : channelList) {
                routeMessage.setStartExp((BigDecimal) channel[1]); // 赋值金额区间
                routeMessage.setEndExp((BigDecimal) channel[2]); // 赋值金额区间
                logger.error("BankRouteServiceImpl getNormalChannelCodes: " + channel[0]);
                channels.add((String) channel[0]);
            }
        }
        return channels;
    }

    @Override
    protected BaseBisBankExtConfig getNormalBankRoute(RouteMessage routeMessage) {
        // TODO Auto-generated method stub
        return null;
    }

}
